
package com.trydofor.id.exec;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;

import com.trydofor.aloe.exception.Exceptions;
import com.trydofor.id.doer.shell.ArgChecker;
import com.trydofor.id.doer.shell.Command;
import com.trydofor.id.doer.shell.Executer;
import com.trydofor.id.doer.shell.Outcome;

/**
 * @author : Shi Rongjiu (www.trydofor.com)
 */
public class SystemExe implements Executer {
    
    private final Command addClassPath;
    private final Command classForName;
    
    /**
     * constructor
     */
    public SystemExe() {
        addClassPath = SystemCmd.addClassPath();
        classForName = SystemCmd.classForName();
    }
    
    /**
     * {@inheritDoc}
     */
    public Outcome execute(Command command, Map<String, String> argdata) {
        
        String err = ArgChecker.check(command, argdata);
        if (err != null) return new Outcome(-1, null, err);
        
        if (addClassPath.getAlias().equals(command.getAlias())) {
            return addClassPath(command, argdata);
        }
        else if (classForName.getAlias().equals(command.getAlias())) {
            return classForName(command, argdata);
        }
        return new Outcome(-1, null, "Command is unsupported:" + command);
    }
    
    // ------------------
    private Outcome classForName(Command command, Map<String, String> argdata) {
        try {
            String clas = argdata.get("class");
            Class.forName(clas);
            return new Outcome(0, "Class.forName()" + clas, null);
        }
        catch (Exception e) {
            return new Outcome(-1, null, Exceptions.printStackTrace(e));
        }
    }
    
    private Outcome addClassPath(Command command, Map<String, String> argdata) {
        try {
            String path = argdata.get("path").trim();
            URL url = null;
            File f = new File(path);
            if (f.exists()) {
                url = f.toURI().toURL();
            }
            else {
                url = new URL(path);
            }
            // bad hack
            URLClassLoader ucl = (URLClassLoader) ClassLoader.getSystemClassLoader();
            Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
            method.setAccessible(true);
            method.invoke(ucl, new Object[] { url });
            return new Outcome(0, "add to class path: " + path, null);
        }
        catch (Exception e) {
            return new Outcome(-1, null, Exceptions.printStackTrace(e));
        }
    }
}
